String.format = function (formatter) {
    var _args = [].slice.apply(arguments, [1]);
    return formatter.replace(/\{(\d+)\}/g, function (match, g1, position, str) {
        return (_args[g1] || match);
    });
};

Date.begin_of_date = function (date) {
    start = $.datepicker.parseDate('yyyy-mm-dd', $.datepicker.formatDate("yyyy-mm-dd", date));
    return start;
};

Date.prototype.format = function (format) {
    var o = {
        "M+": this.getMonth() + 1,
        "d+": this.getDate(),
        "h+": this.getHours(),
        "m+": this.getMinutes(),
        "s+": this.getSeconds(),
        "q+": Math.floor((this.getMonth() + 3) / 3),
        "S": this.getMilliseconds()
    }
    if (/(y+)/.test(format)) {
        format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    }
    for (var k in o) {
        if (new RegExp("(" + k + ")").test(format)) {
            format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
        }
    }
    return format;
};

angular.module('CvirtUtils', ['interval', 'CvirtServices']).factory("$pollingPool", function ($interval, $rootScope) {
    var jobs = [];
    var activity_jobs = [];
    var activity_callback = {};
    return {
        add_activity_callback: function (aid, callback) {
            activity_callback[aid] = callback;
        },
        add: function (call_back, delay, is_activity) {
            delay = delay || 3000;
            //activity_callback参数传递给activity刷新任务，对于一般任务没有意义
            var job = $interval(function () {
                $rootScope.noload = true; //忽略loading拦截
                try {
                    call_back(activity_callback)
                } catch (e) {
                    console.log(e);
                }
                $rootScope.noload = false;
            }, delay);
            if (is_activity) {
                activity_jobs.push(job);
                console.log('add activity job')
            } else {
                jobs.push(job);
                console.log('add normal job')
            }

            return job;
        },
        clear: function (include_activity) {
            if (include_activity == undefined) {
                jbs = jobs;
                console.log('clear normal jobs, number = ' + jobs.length);
            } else {

                var jbs = jobs.concat(activity_jobs);
                console.log('clear all jobs, number = ' + jobs.length);
                activity_jobs = [];
            }
            angular.forEach(jobs, function (i) {
                i.cancel();
            })

            jobs = [];

        }
    }

})

    .factory("Util", function ($rootScope, $location, $window, $dialog, $q, License) {

        var message_box = function (title, msg, btns, callback) {
            $dialog.messageBox(title, msg, btns, {dialogClass: 'modal alert-message'}).open().then(function (result) {
                (callback || angular.noop)(result);
            });
        };
        return {
            getCookie: function (name) {
                var cookies = document.cookie.split(";");
                for (var i = 0; i < cookies.length; i++) {
                    var cookie = cookies[i].split("=");
                    if (name == cookie[0])
                        return cookie[1];
                }
                return null;
            },
            update: function (dst, update_data) {
                angular.forEach(dst, function (vm) {
                    angular.forEach(update_data, function (data) {
                        if (data.id == vm.id) {
                            angular.extend(vm, data);
                        }
                    });
                });
            },
            remove: function (dst, update_data) {
                angular.forEach(dst, function (vm) {
                    angular.forEach(update_data, function (data) {
                        if (data.id == vm.id) {
                            dst.pop(vm)
                        }
                    });
                });
            },
            flatten: function (arr, target) {
                var ret = [];
                for (var i = 0; i < arr.length; i++) {
                    if (arr[i][target] instanceof Array) {
                        for (var j = 0; j < arr[i][target].length; j++) {
                            ret.push(arr[i][target][j]);
                        }
                    } else {
                        ret.push(arr[i][target]);
                    }
                }
                return ret;
            },
            update_activities: function (data) {
                if (data.activities) {
                    for (var i = 0; i < data.activities.length; i++) {
                        $rootScope.activities.unshift(data.activities[i]);
                    }
                }
            },
            confirm: function (msg, succ, fail) {
                var btns = [
                    {result: false, label: '取消'},
                    {result: true, label: '确定', cssClass: 'btn-primary mini'}
                ];
                message_box("提示信息", msg, btns, function (result) {
                    if (result) {
                        (succ || angular.noop)();
                    } else {
                        (fail || angular.noop)();
                    }
                });
            },
            alert: function (msg) {
                var btns = [
                    {result: 'ok', label: '确定', cssClass: 'btn-primary mini'}
                ];
                message_box("提示信息", msg, btns);
            },
            check_records: function ($scope, target_name, min, max) {
                $scope.min_msg = ($scope.min_msg || "你至少应该选择{0}个");
                $scope.max_msg = ($scope.max_msg || "你不能选择超过{0}个");
                var items = $.grep($scope[target_name], function (item) {
                    return $scope.selected[item.id];
                }), _this = this, defer = $q.defer();
                if (items.length < min) {
                    var msg = String.format($scope.min_msg, min);
                    _this.alert(msg);
                    defer.reject(msg);
                    return false;
                }
                if (max != undefined) {
                    if (items.length > max) {
                        var msg = String.format($scope.max_msg, min);
                        _this.alert(msg);
                        defer.reject(msg);
                        return false;
                    }
                }
                return true;
            },
            bind: function ($scope, target_name) {
                $scope.min_msg = ($scope.min_msg || "你至少应该选择{0}个");
                $scope.max_msg = ($scope.max_msg || "你不能选择超过{0}个");
                var items = $.grep($scope[target_name], function (item) {
                    return $scope.selected[item.id];
                }), _this = this, defer = $q.defer(), _notvalidate = false;
                return {
                    select: function (min, max) {
                        if (items.length < min) {
                            var msg = String.format($scope.min_msg, min);
                            _this.alert(msg);
                            defer.reject(msg);
                            _notvalidate = true;
                        }
                        if (max != undefined) {
                            if (items.length > max) {
                                var msg = String.format($scope.max_msg, min);
                                _this.alert(msg);
                                defer.reject(msg);
                                _notvalidate = true;
                            }

                        }

                        return {
                            then: function (fn) {
                                defer.promise.then(fn);
                                defer.resolve(items);
                            },
                            confirm: function (msg) {
                                if (!_notvalidate) {
                                    _this.confirm(msg, function () {
                                        defer.resolve(items);
                                    }, function () {
                                        defer.reject('User Cancelled.');
                                    });
                                }
                                return defer.promise;

                            }
                        };
                    }
                }
            },
            pagination: function ($scope, target_name, page_size) {
                $scope.current_page = 0;
                $scope.page_size = page_size;

                $scope.$watch('current_page', function (current, old) {
                    if (current == 0) {
                        $scope.prev_class = 'disabled';
                    } else {
                        $scope.prev_class = '';
                    }
                    if (current == $scope.page_count() - 1) {
                        $scope.next_class = 'disabled';
                    } else {
                        $scope.next_class = '';
                    }
                });

                $scope.prev = function () {
                    if ($scope.current_page > 0) {
                        $scope.current_page -= 1;
                    }
                };

                $scope.page = function (i) {
                    $scope.current_page = i;
                };

                $scope.next = function () {
                    if ($scope.current_page < $scope.page_count() - 1) {
                        $scope.current_page += 1;
                    }
                };

                $scope.page_count = function () {
                    if ($scope[target_name]) {
                        return Math.ceil($scope[target_name].length / $scope.page_size);
                    } else {
                        return 0;
                    }
                };

                $scope.should_hide = function () {
                    return ($scope[target_name] && $scope[target_name].length <= $scope.page_size);
                };

                $scope.unselected_all = function () {
                    $scope.selected_all = false;
                };

                $scope.$watch('selected_all', function (new_value, old_value) {
                    if (new_value != undefined) {
                        $scope[target_name].filter(function (target, i) {
                            if (i >= $scope.current_page * $scope.page_size && i < $scope.current_page * $scope.page_size + $scope.page_size) {
                                $scope.selected[target.id] = new_value;
                            }
                        });
                    }
                });
            },
            paginate: function ($scope, target_name) {

                $scope.current_page = 0;
                $scope.total_page = 0;
                $scope.total_count = 0;
                $scope.page_sizes = [2, 5, 10, 20, 30, 50, 100];

                $scope.prev = function () {
                    if ($scope.current_page > 0) {
                        $scope.current_page -= 1;
                    }
                };

                $scope.page_count = function () {
                    return ($scope.total_page || 0);
                };

                $scope.next = function () {
                    if ($scope.current_page < $scope.page_count() - 1) {
                        $scope.current_page += 1;
                    }
                };

                $scope.page = function (current_page) {
                    $scope.current_page = current_page;
                }

                $scope.change = function (page_size) {
                    $scope.page_size = page_size;
                    $scope.current_page = 0;
                    $scope.service($scope.current_page + 1, $scope.page_size);
                }

                $scope.$watch('current_page', function (current, old) {
                    if (current == 0) {
                        $scope.prev_class = 'disabled';
                    } else {
                        $scope.prev_class = '';
                    }
                    if (current == $scope.page_count() - 1) {
                        $scope.next_class = 'disabled';
                    } else {
                        $scope.next_class = '';
                    }

                    /*
                     if(!$scope.$$phase) {
                     $scope.$apply(function(){
                     $scope.service(current + 1, 2);
                     });
                     }else{

                     }
                     */

                    $scope.service(current + 1, $scope.page_size);


                });


                $scope.should_hide = function () {
                    return ($scope.total_count <= $scope.page_size);
                };

                $scope.unselected_all = function () {
                    $scope.selected_all = false;
                };

                $scope.$watch('selected_all', function (new_value, old_value) {
                    if (new_value != undefined) {
                        $scope[target_name].filter(function (target, i) {
//                            if (i >= $scope.current_page * $scope.page_size && i < $scope.current_page * $scope.page_size + $scope.page_size) {
                                $scope.selected[target.id] = new_value;
//                            }
                        });
                    }
                });
            },
            breadcrumb: function (name) {
                var tree = $.fn.zTree.getZTreeObj('search-tree');
                var node = tree.getNodeByParam('name', name, null), bc = [];
                while (node != null) {
                    bc.push(node.name);
                    node = node.getParentNode();
                }
                bc.reverse();
                return bc.join(' > ');
            },
            bind_tab: function ($scope) {
                //$scope.$on('$locationChangeStart', function(e){
                //if($location.absUrl().split('#').length >= 3){
                //  e.preventDefault();
                //}
                //});
                //$scope.$on('$locationChangeSuccess', function(e){
                //});

                var hs = $location.absUrl().split('#');
                if (hs.length == 3) {
                    var h = hs[2];
                    //$('.tabbable a:first').tab('show'); //Here is for wrong hash input.
                    $('.tabbable a[href="#' + h + '"]').tab('show');//.closest('li').addClass('active');
                    if ($scope.templates) {
                        $scope.current_template = $scope.templates[h];
                    }
                }
                var subname = function (sub) {
                    var data = {
                        overview: "概览",
                        events: "事件",
                        hosts: "主机",
                        vms: "虚拟机",
                        networks: "网络",
                        storages: "存储",
                        backups: "备份",
                        tasks: "任务",
                        monitors: "监控",
                        disk: "磁盘",
                        templates: "模板"
                    };
                    return data[sub];
                }
                $scope.shortcut = {
                    url: $location.absUrl(),
                    subname: subname(hs[2] || "overview")
                }

                $('a[data-toggle="tab"]').on('shown', function (e) {
                    $scope.$apply(function () {
                        $location.hash(e.target.hash.substr(1));
                    });
                    //$('#directives-calendar').find('.calendar').fullCalendar('render');
                    return false;
                });
            },
            dialog: function (template_url, ctrl_name, $scope, opts) {
                var options = angular.extend({
                    backdrop: true,
                    keyboard: true,
                    backdropClick: false,
                    templateUrl: template_url,
                    controller: ctrl_name
                }, opts)
                var d = $dialog.dialog(options);
                d.context_scope = $scope;
                d.open().then(function (result) {
                    if (result) {
                        alert('dialog closed with result: ' + result);
                    }
                });
            },
            bookmark: function ($scope, name, desc) {

                var deferred = $q.defer(), _this = this;

                var shortcut = $scope.shortcut;

                _this.dialog("/static/partials/shortcuts/_shortcut.html",
                    'ShortcutDialogCtrl', $scope, {backdropClick: false, dialogClass: 'modal mini'});

                if (!$rootScope.shortcuts) {
                    Shortcut.query({}, function (data) {
                        $rootScope.shortcuts = data;
                        deferred.resolve();
                    });
                } else {
                    deferred.resolve();
                }
            },
            update_list: function (list, data) {
                if (list) {
                    data.id = 10 + Math.round(Math.random() * 10);
                    list.unshift(data);
                }
            },
            overview: function ($scope) {

                $scope.normal_hosts = []
                $scope.shutdown_hosts = []
                $scope.maitain_hosts = []
                $scope.exception_hosts = []
                //0-维护模式,1-未激活,2-已激活,3-关机
                angular.forEach($scope.hosts_o, function (host) {
                    if (host.status == 2) {
                        $scope.normal_hosts.push(host);
                    } else if (host.status == 3) {
                        $scope.shutdown_hosts.push(host);
                    } else if (host.status == 0) {
                        $scope.maitain_hosts.push(host);
                    } else if (host.status == 1) {
                        $scope.exception_hosts.push(host);
                    }
                });

                $scope.normal_vms = []
                $scope.shutdown_vms = []
                $scope.exception_vms = []

                angular.forEach($scope.vms_o, function (vm) {
                    if (vm.status == 'running') {
                        $scope.normal_vms.push(vm);
                    } else if (vm.status == 'shutdown') {
                        $scope.shutdown_vms.push(vm);
                    } else if (vm.status == 'exception') {
                        $scope.exception_vms.push(vm);
                    }
                });

                $scope.storageok = [];
                $scope.storageerror = [];
                angular.forEach($scope.storages_o, function (s) {
                    if (s.status == 'running') {
                        $scope.storageok.push(s);
                    } else if (s.status == 'failed') {
                        $scope.storageerror.push(s);
                    }
                });
            },
            convert2utc: function (date) {
                return date;
//        offset=date.getTimezoneOffset()*60000; //获得当地时间偏移的毫秒数
//        utc = date.getTime() - offset;
//        date = new Date(utc);
//        var h = date.getHours();
//        var mn = date.getMinutes();
//        var s = date.getSeconds();
//        var m = date.getMonth();
//        var d = date.getDate();
//        var year = date.getFullYear();
//        var offset = date.getTimezoneOffset()/60;
//        date = new Date(Date.UTC(year,m,d,h+offset,mn,s));
//        return date;
            },
            convert2local: function (date) {
                return date;
//        offset=date.getTimezoneOffset()*60000; //获得当地时间偏移的毫秒数
//        utc = date.getTime() + offset;
//        date = new Date(utc);
//        return date;
            },
            decode_error_msg: function (msg) {
                try {
                    var errormsg = msg.replace(/"/g, '').replace('\\n', '');//rest response中的data会有引号和回车，我们去除掉
                    if (errormsg.indexOf('b64_') == 0) {//以b64_开头
                        errormsg = errormsg.replace('b64_', '');
                        return Base64.decode(errormsg);
                    }
                } catch (e) {
                }
                return msg;
            }
        };
    });


